#pragma once
#include<iostream>
#include <cstdint>
#include <functional>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unordered_map>
#include <memory>
#include <assert.h>
#include <thread>
#include <vector>
#include <mutex>
#include <sys/eventfd.h>
#include <unistd.h>
#include <condition_variable>
#include <sys/timerfd.h>

#include "log_server.hpp"


class EventLoop;
class Channel;

class TimerWheel;


using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;


// 事件管理
class Channel
{
private:
    int _fd;           // 文件描述符
    uint32_t _events;  // 当前文件描述符想要监听的事件集合
    uint32_t _revents; // epoll返回的就绪事件

    EventLoop *_event_loop;

    using EventCallback = std::function<void()>;

    EventCallback _read_callback;
    EventCallback _write_callback;
    EventCallback _error_callback;
    EventCallback _close_callback;
    EventCallback _event_callback;

public:
    Channel(EventLoop *event_loop, int fd) : _event_loop(event_loop), _fd(fd), _events(0), _revents(0) {}

    int Fd()
    {
        return _fd;
    }

    uint32_t Events()
    {
        return _events;
    }

    void SetREvents(uint32_t events)
    {
        _revents = events;
    }

    // 设置相应的事件
    void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
    void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
    void SetErrorCallback(const EventCallback &cb) { _error_callback = cb; }
    void SetCloseCallback(const EventCallback &cb) { _close_callback = cb; }
    void SetEventCallback(const EventCallback &cb) { _event_callback = cb; }

    // 判断相应的事件是否就绪
    bool ReadAble() { return (_events & EPOLLIN); }
    bool WriteAble() { return (_events & EPOLLOUT); }

    // 确保相应的事件被监听
    void EanbleRead()
    {
        _events = _events | EPOLLIN;
    }

    void EanbleWrite()
    {
        _events = _events | EPOLLOUT;
    }

    // 关闭相应事件的监听
    void DisableRead()
    {
        _events &= ~EPOLLIN;
    }

    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
    }

    void DisableAll()
    {
        _events = 0;
    }

    // 移除事件
    void Remove();
    void Update();

    // 事件处理，事件触发就调用这个函数,根据就绪状态执行相应的函数

    void HandleEvent()
    {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_read_callback)
                _read_callback();
        }

        // 有可能释放连接的操作一次只能释放一个
        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
                _write_callback();
        }
        else if (_revents & EPOLLERR)
        {
            if (_error_callback)
                _error_callback();
        }
        else if (_revents & EPOLLHUP)
        {
            if (_close_callback)
                _close_callback();
        }
        if (_event_callback)
            _event_callback();
    }
};

#define MAX_EPOLLEVENTS 1024
// 描述符事件监控
class Poller
{
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];

    std::unordered_map<int, Channel *> _channels;

private:
    // 对于epoll的直接操作，添加，修改，删除
    void Update(Channel *channel, int op)
    {
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;

        ev.events = channel->Events();

        int ret = epoll_ctl(_epfd, op, fd, &ev);
        if (ret < 0)
        {
            ERR_LOG("epoll_ctl error");
        }
        return;
    }

    // 判断Channel是否添加了事件监控
    bool HasChannel(Channel *channel)
    {
        auto it = _channels.find(channel->Fd());
        if (it == _channels.end())
        {
            return false;
        }
        return true;
    }

public:
    // 创建epoll
    Poller()
    {
        _epfd = epoll_create1(MAX_EPOLLEVENTS);
        if (_epfd < 0)
        {
            ERR_LOG("epoll create error");
            abort(); // 退出程序
        }
    }

    // 添加或者修改监控事件
    void UpdateEvent(Channel *channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
        {
            // 不存在则添加该事件
            _channels.insert(std::make_pair(channel->Fd(), channel));
            Update(channel, EPOLL_CTL_ADD);
            return;
        }

        Update(channel, EPOLL_CTL_MOD);
    }

    // 移除监控事件
    void RemoveEvent(Channel *channel)
    {
        auto it = _channels.find(channel->Fd());
        if (it != _channels.end())
        {
            _channels.erase(it);
        }
        Update(channel, EPOLL_CTL_DEL);
    }

    // 开始监控，返回活跃连接
    void Poll(std::vector<Channel *> *active)
    {
        int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
        if (nfds < 0)
        {
            if (errno == EAGAIN)
            {
                return;
            }
            ERR_LOG("epoll wait error");
            abort();
        }

        for (int i = 0; i < nfds; i++)
        {
            auto it = _channels.find(_evs[i].data.fd);

            assert(it != _channels.end());

            it->second->SetREvents(_evs[i].events);
            active->push_back(it->second);
        }
        return;
    }
};


// 线程池类,与线程1:1对应关联
class EventLoop
{
private:
    using Functor = std::function<void()>;

    std::thread::id _thread_id; // 线程id

    int _event_fd;              // eventfd唤醒I/O事件监控
    std::unique_ptr<Channel> _event_channel;

    Poller _poller;              // 进行所有描述符的事件监控
    std::vector<Functor> _tasks; // 任务池

    std::mutex _mutex; // 实现任务池的线程安全

    //TimerWheel _timer_wheel;//定时器


    std::unique_ptr<TimerWheel> _timer_wheel;
public:
    // 执行任务池中的所有任务
    void RunAllTask()
    {
        std::vector<Functor> functor;

        // 将相应的任务换到functor
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.swap(functor);
        }

        // 之后的任务执行不需要再加锁
        for (auto &f : functor)
        {
            f();
        }
        return;
    }

    // 创建
    static int CreateEventFd()
    {
        int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (efd < 0)
        {
            ERR_LOG(" create event error");
            abort();
        }
        return efd;
    }

    void ReadEventfd()
    {
        uint64_t res = 0;
        int ret = read(_event_fd, &res, sizeof(res));
        if (ret <= 0)
        {
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            ERR_LOG("read eventfd error");
            abort();
        }
        return;
    }

    // 唤醒事件
    void WeakUpEventfd()
    {
        uint64_t val = 1;
        int ret = write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            ERR_LOG("write eventfd errno");
            abort();
        }
        return;
    }

public:
    EventLoop() : _thread_id(std::this_thread::get_id()), _event_fd(CreateEventFd()), _event_channel(new Channel(this, _event_fd)),_timer_wheel(std::make_unique<TimerWheel>(this))
    {
        // 添加可读事件回调，
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));

        // 启动读事件的监控
        _event_channel->EanbleRead();
    }

    void Start()
    {
        while (1)
        {
            // 事件监控
            std::vector<Channel *> actives;
            _poller.Poll(&actives);

            // 事件处理
            for (auto &channel : actives)
            {
                channel->HandleEvent();
            }

            // 执行任务
            RunAllTask();
        }
    }

    // 判断当前线程是否是EventLoop对应的线程
    bool IsInLoop()
    {
        return (_thread_id == std::this_thread::get_id());
    }

    bool AssertInLoop()
    {
        assert(_thread_id == std::this_thread::get_id());
    }

    // 判断将要执行的任务是否在当前线程中，如果是就执行，不是就压入队列
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            cb();
            return;
        }
        return QueueInLoop(cb);
    }

    

    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(cb);
        }
        // 唤醒事件
        WeakUpEventfd();
    }

    // 添加和修改描述符的事件监控
    void UpdateEvent(Channel *channel)
    {
        return _poller.UpdateEvent(channel);
    }

    // 移除事件描述符监控
    void RemoveEvent(Channel *channel)
    {
        return _poller.RemoveEvent(channel);
    }

    void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc&cb)
    {
        return _timer_wheel->TimerAdd(id,delay,cb);
    }

    void TimerRefresh(uint64_t id)
    {
        return _timer_wheel->TimerRefresh(id);
    }

    void TimerCancel(uint64_t id)
    {
        return _timer_wheel->TimerCancel(id);
    }

    bool HasTimer(uint64_t id)
    {
        return _timer_wheel->HasTimer(id);
    }
};

class LoopThread
{
private:
    std::mutex _mutex;
    std::condition_variable _cond;
    EventLoop *_loop;
    std::thread _thread;

private:
    void ThreadEntry()
    {
        EventLoop loop;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _loop = &loop;
            _cond.notify_all();
        }
        loop.Start();
    }

public:
    LoopThread() : _loop(NULL), _thread(std::thread(&LoopThread::ThreadEntry, this))
    {
    }

    // 返回当前线程关联的指针
    EventLoop *GetLoop()
    {
        EventLoop *loop = NULL;

        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _cond.wait(_lock, [&]()
                       { return _loop != NULL; });

            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool
{

private:
    int _thread_count;
    int _nex_idx;
    EventLoop *_baseloop;

    std::vector<LoopThread *> _threads;

    std::vector<EventLoop *> _loops;

public:
    LoopThreadPool(EventLoop *baseloop) : _thread_count(0), _nex_idx(0), _baseloop(baseloop)
    {
    }

    void SetThreadCount(int count) { _thread_count = count; }

    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; i++)
            {
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
        return;
    }

    EventLoop *NextLoop()
    {
        if (_thread_count == 0)
        {
            return _baseloop;
        }
        _nex_idx = (_nex_idx + 1) % _thread_count;
        return _loops[_nex_idx];
    }
};


class TimerTask
{
private:
    uint64_t _id;      // 定时任务器对象ID
    uint32_t _timeout; // 定时任务的超时时间
    bool _canceled;

    TaskFunc _task_cb;    // 定时器对象要执行的定时任务
    ReleaseFunc _release; // 用于删除TimerWheel中保存的定时器对象信息

public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb) : _id(id), _timeout(delay), _task_cb(cb)
    {
    }

    ~TimerTask()
    {
        if (_canceled == false)
            _task_cb();

        _release();
    }

    void Cancel() { _canceled = true; }

    void SetRelease(const ReleaseFunc &release)
    {
        _release = release;
    }

    uint32_t DelayTime()
    {
        return _timeout;
    }
};

class TimerWheel
{
private:
    using WeakTask = std::weak_ptr<TimerTask>;
    using PtrTask = std::shared_ptr<TimerTask>;
    int _tick;

    int _capacity; // 表盘最大数量

    std::vector<std::vector<PtrTask>> _wheel;

    std::unordered_map<uint64_t, WeakTask> _timers;

    EventLoop *_loop;
    int _timerfd;
    std::unique_ptr<Channel> _timer_channel;

private:
    // 移除定时时间轮
    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);

        if (it != _timers.end())
        {
            _timers.erase(it);
        }
    }

    static int CreateTimerfd()
    {
        int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);

        if (timerfd < 0)
        {
            ERR_LOG("timer create error");
            abort();
        }
        itimerspec itime;
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0;

        timerfd_settime(timerfd, 0, &itime, NULL);

        return timerfd;
    }

    int ReadTimefd()
    {
        uint64_t times;

        int ret = read(_timerfd, &times, 8);

        if (ret < 0)
        {
            ERR_LOG("read error");
            abort();
        }
        return times;
    }

    // 推进时间
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();
    }

    void OnTime()
    {
        int times = ReadTimefd();

        // 根据实际相应的超时时间执行相应的任务
        for (int i = 0; i < times; i++)
        {
            RunTimerTask();
        }
    }

    void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &cb)
    {
        PtrTask pt(new TimerTask(id, delay, cb));

        // 任务释放时需要从时间轮中移除任务
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));

        int pos = (_tick + delay) % _capacity;

        // 添加到时间轮中
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }

    void TimerRefreshInLoop(uint64_t id)
    {
        auto it = _timers.find(id);

        if (it == _timers.end())
        {
            return;
        }

        PtrTask pt = it->second.lock();

        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }

    void TimerCancleInLoop(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it != _timers.end())
        {
            return;
        }

        PtrTask pt = it->second.lock();

        if (pt)
            pt->Cancel();
    }

    public:

       TimerWheel(EventLoop* loop):_capacity(60),_tick(0),_wheel(_capacity),_loop(loop),
       _timerfd(CreateTimerfd()),_timer_channel(new Channel(_loop,_timerfd))
       {
        _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime,this));
        _timer_channel->EanbleRead();
       }

       void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb);

       void TimerRefresh(uint64_t id);

       void TimerCancel(uint64_t id);

       bool HasTimer(uint64_t id)
       {
        auto it=_timers.find(id);
        if(it==_timers.end())
        {
            return false;
        }
        return true;
       }
};

void TimerWheel::TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop,this,id,delay,cb));
}

void TimerWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop,this,id));
}

void TimerWheel::TimerCancel(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancleInLoop,this,id));
}


